package com.microservice.base.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.microservice.base.common.utils.ImageUtil;
import com.microservice.base.entity.*;
import com.microservice.base.mapper.hikcommon.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 调用海康接口的工具类
 *
 * @author jbx
 * @package_name com.microservice.base.common.utils
 * @create_date 2020/12/10 11:15
 */
@Component
@Transactional
public class HikInterfacePush {
    @Autowired
    OrgMP orgMP;
    @Autowired
    PersonMP personMP;
    @Autowired
    FaceMP faceMP;
    Logger logger = LoggerFactory.getLogger(HikInterfacePush.class);
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

    // 调用组织的批量增加
    // 需要的数据是组织编号.组织名称,父组织结点
    // 单次提交的最大记录是1000条
    public void orgBatchAdd() {
        List<Org> orgs = orgMP.queryUpdate(2);
        Map<String, Object> maxLevels = orgMP.getMaxLevel();
        if (orgs.size() > 0) {
            Integer maxLevel = (Integer) maxLevels.get("maxLevel");
            List insertList = new ArrayList();
            for (int i = 1; i <= maxLevel; i++) {
                List<Org> orgs1 = orgMP.orgByLevelAndStatus(i, 0, 2);
                JSONArray jsonArray = new JSONArray();
                if (orgs1 != null && orgs1.size() > 0) {
                    for (Org org : orgs1) {
                        JSONObject jo = new JSONObject();
                        jo.put("orgIndexCode", org.getOrgId());
                        jo.put("orgName", org.getOrgName());
                        jo.put("parentIndexCode", org.getParentOrgId());
                        jsonArray.add(jo);
                    }
                    try {
                        String s =
                                HikConnection.pushHik("/api/resource/v1/org/batch/add", jsonArray.toString());
                        logger.error("新增组织同步" + s);
                        // 只有在同步成功过去之后,才进行org表状态的修改
                        JSONObject jsonObject = JSONObject.parseObject(s);
                        if ("success".equals(jsonObject.get("msg"))) {
                            for (Org org : orgs1) {
                                org.setOperation(0);
                                insertList.add(org);
                            }
                        } else {
                            logger.error("批量同步组织数据发生异常,请查看海康返回信息");
                        }
                    } catch (Exception e) {
                        logger.error("连接海康服务器失败,组织数据批量新增失败");
                    }
                }
            }
            if (insertList.size() > 0) {
                orgMP.replaceUpdate(insertList);
            }
            logger.error("成功.....新增海康数据库组织数据");
        } else {
            logger.error("没有需要批量新增的组织数据");
        }
    }

    // 调用组织的更新
    // 需要的参数:orgIndexCode->组织id,orgName->组织名称
    public void orgUpdate() {
        // 封装为json
        List<Org> orgsupdate = orgMP.queryUpdate(1);
        List<Org> orgsdelete = orgMP.queryDelete(1);
        // 获取全部的更新数据,要进行更新还是删除的判断
        if (orgsupdate.size() > 0) {
            List updateList = new ArrayList();
            for (Org org : orgsupdate) {
                // 修改只能单个修改
                JSONObject jo = new JSONObject();
                jo.put("orgIndexCode", org.getOrgId());
                jo.put("orgName", org.getOrgName());
                try {
                    String s = HikConnection.pushHik("/api/resource/v1/org/single/update", jo.toString());
                    logger.error("修改组织同步记录,组织id:" + org.getOrgId() + ";" + s);
                    // 同步成功后更改org表的状态
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    if ("success".equals(jsonObject.get("msg"))) {
                        org.setOperation(0);
                        updateList.add(org);
                    } else {
                        logger.error("修改组织数据失败,请查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,未能更新组织数据");
                }
            }
            if (updateList.size() > 0) {
                orgMP.replaceUpdate(updateList);
            }
            logger.error("成功.....更新海康数据库组织数据");
        } else {
            logger.error("没有需要更新的组织数据");
        }
        // 组织数据很少超过1000,故不做1000删除的限制
        // 删除是批量删除
        // 仅支持删除无子结点且组织下不存在人员的组织,故删除要从level从大到小删
        if (orgsdelete.size() > 0) {
            Map<String, Object> maxLevels = orgMP.getMaxLevel();
            Integer maxLevel = (Integer) maxLevels.get("maxLevel");
            for (int i = maxLevel; i > 0; i--) {
                JSONObject jo = new JSONObject();
                List<Org> orgByLevelAndStatus = orgMP.orgByLevelAndStatus(i, -1, 1);
                if (orgByLevelAndStatus.size() != 0) {
                    String[] strings = new String[orgByLevelAndStatus.size()];
                    for (int j = 0; j < orgByLevelAndStatus.size(); j++) {
                        strings[j] = orgByLevelAndStatus.get(j).getOrgId();
                    }
                    jo.put("indexCodes", strings);
                    try {
                        String s = HikConnection.pushHik("/api/resource/v1/org/batch/delete", jo.toString());
                        logger.error("删除组织同步记录" + s);
                        JSONObject jsonObject = JSONObject.parseObject(s);
                        if ("success".equals(jsonObject.get("msg"))) {
                            for (Org org : orgByLevelAndStatus) {
                                orgMP.updateOperation(0, org.getOrgId());
                            }
                        } else {
                            logger.error("删除组织数据格式失败,请查看海康返回数据");
                        }
                    } catch (Exception e) {
                        logger.error("连接海康服务器失败,未能删除组织数据");
                    }
                }
            }
            logger.error("成功.....删除海康数据库组织数据");
        } else {
            logger.error("没有需要删除的组织数据");
        }
    }

    // ==========================================================================================
    // 人员的批量增加
    // 单次操作上限为1000条
    public void personBatchAdd() {
        // 先查询person表中新增人员信息
        List<Person> insertpeople = personMP.queryUpdate(2);
        if (insertpeople.size() > 0) {
            List insertList = new ArrayList();
            for (int i = 0; i <= insertpeople.size() / 1000; i++) {
                JSONArray jsonArray = new JSONArray();
                List<Person> people =
                        insertpeople.stream().skip(i * 1000).limit(1000).collect(Collectors.toList());
                for (Person person : people) {
                    JSONObject jo = new JSONObject();
                    jo.put("personId", person.getPersonId());
                    jo.put("personName", person.getPersonName());
                    jo.put("gender", person.getSex());
                    jo.put("orgIndexCode", person.getOrgId());
                    jo.put("certificateType", person.getCertType() + "");
                    jo.put("certificateNo", person.getCertNum());
                    jo.put("jobNo", person.getEmployeeId());
                    jsonArray.add(jo);
                }
                try {
                    String s =
                            HikConnection.pushHik("/api/resource/v1/person/batch/add", jsonArray.toString());
                    logger.error("新增人员记录" + s);
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    if ("success".equals(jsonObject.get("msg"))) {
                        for (Person person : people) {
                            person.setOperation(0);
                            insertList.add(person);
                        }
                    } else {
                        logger.error("新增人员数据发生异常,请查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,人员批量新增失败");
                }
            }

            // 新增完人员后,进行一卡通的新增
            // 查询有一卡通的有效信息,因为一旦重复会导致后面的数据无法导入,因此1条条的导入
            for (Person person : insertpeople) {
                JSONObject total = new JSONObject();
                JSONArray jsonArray = new JSONArray();
                if ("0".equals(person.getCardStatus())) {
                    JSONObject jo = new JSONObject();
                    jo.put("cardNo", new BigInteger(person.getCardHex(), 16).toString());
                    jo.put("personId", person.getPersonId());
                    jo.put("orgIndexCode", person.getOrgId());
                    jsonArray.add(jo);
                }
                if (jsonArray.size() > 0) {
                    total.put("cardList", jsonArray);
                    total.put("startDate", "2020-12-12");
                    total.put("endDate", "2037-12-30");
                    String s = HikConnection.pushHik("/api/cis/v1/card/bindings", total.toString());
                    logger.error("新增人员卡片信息" + s);
                }
            }

            if (insertList.size() > 0) {
                personMP.replaceUpdate(insertList);
            }
            logger.error("成功.....新增海康人员数据");
        } else {
            logger.error("没有需要批量新增的人员数据");
        }
    }

    // 调用人员和卡片的更新
    public void PersonUpdate() {
        // 封装为json
        List<Person> peopleUpdate = personMP.queryUpdate(1);
        List<Person> peopleDelete = personMP.queryDelete(1);
        // 获取全部的更新数据,要进行更新还是删除的判断

        if (peopleUpdate.size() > 0) {
            // 修改是单个修改
            for (Person person : peopleUpdate) {
                JSONObject jo = new JSONObject();
                jo.put("personId", person.getPersonId());
                jo.put("personName", person.getPersonName());
                jo.put("gender", person.getSex());
                jo.put("orgIndexCode", person.getOrgId());
                jo.put("certificateType", person.getCertType() + "");
                jo.put("certificateNo", person.getCertNum());
                jo.put("jobNo", person.getEmployeeId());
                try {
                    String s = HikConnection.pushHik("/api/resource/v1/person/single/update", jo.toString());
                    logger.error("修改人员记录,人员id:" + person.getPersonId() + ";" + s);
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    if ("success".equals(jsonObject.get("msg"))) {
                        personMP.updateOperation(0, person.getPersonId());
                    } else {
                        logger.error("修改人员信息发生异常,请查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,人员更新失败");
                }
                try {
                    if (person.getCardStatus() != null && !"0".equals(person.getCardStatus())) {
                        // 删除卡片操作
                        JSONObject deleteCard = new JSONObject();
                        deleteCard.put("cardNumber", new BigInteger(person.getCardHex(), 16).toString());
                        deleteCard.put("personId", person.getPersonId());
                        String deleteCards =
                                HikConnection.pushHik("/api/cis/v1/card/deletion", deleteCard.toString());
                        logger.error("成功删除卡片信息:" + deleteCards);
                    } else if ("0".equals(person.getCardStatus())) {
                        JSONObject addCard = new JSONObject();
                        JSONArray addCards = new JSONArray();
                        JSONObject total = new JSONObject();
                        addCard.put("cardNo", new BigInteger(person.getCardHex(), 16).toString());
                        addCard.put("personId", person.getPersonId());
                        addCard.put("orgIndexCode", person.getOrgId());
                        addCards.add(addCard);
                        total.put("cardList", addCards);
                        total.put("startDate", "2020-12-12");
                        total.put("endDate", "2037-12-30");
                        String s = HikConnection.pushHik("/api/cis/v1/card/bindings", total.toString());
                        logger.error("新增人员卡片信息" + s);
                    }
                } catch (Exception e) {
                    logger.error("更新卡片信息失败,错误信息:" + e);
                }
            }
            logger.error("成功......修改人员和卡片海康数据库");
        } else {
            logger.error("没有需要更新的人员数据");
        }

        // 批量删除
        if (peopleDelete.size() > 0) {
            for (int i = 0; i <= peopleDelete.size() / 1000; i++) {
                JSONObject jo = new JSONObject();
                String[] strings = new String[1000];
                List<Person> people =
                        peopleDelete.stream().skip(i * 1000).limit(1000).collect(Collectors.toList());
                for (int j = 0; j < people.size(); j++) {
                    strings[j] = peopleDelete.get(j).getOrgId();
                }
                jo.put("personIds", strings);
                try {
                    String s = HikConnection.pushHik("/api/resource/v1/person/batch/delete", jo.toString());
                    logger.error("删除人员记录" + s);
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    if ("success".equals(jsonObject.get("msg"))) {
                        for (Person person : people) {
                            personMP.updateOperation(0, person.getPersonId());
                        }
                    } else {
                        logger.error("删除人员信息出现异常,请查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,未能批量删除数据");
                }
            }
            logger.error("成功.....删除海康人员数据库");
        } else {
            logger.error("没有需要删除的人员数据");
        }
    }

    // ==============================================================================================
    // 调用人脸信息的单个增加
    // 新增的时候要注意,我们要获取海康返回的face_id存入到数据库中,以备后面的删除和修改使用
    public void faceAdd() {
        // 查询增加的人,增加是单个增加
        List<Face> faces = faceMP.queryUpdate(2);
        if (faces.size() > 0) {
            List<Face> updatefacelist = new ArrayList<>();
            for (Face value : faces) {
                JSONObject jo = new JSONObject();
                jo.put("personId", value.getPersonId());
                jo.put("faceData", ImageUtil.getImgUrlToBase64(value.getFaceUrl()));
                try {
                    String s = HikConnection.pushHik("/api/resource/v1/face/single/add", jo.toString());
                    logger.error("新增人脸记录,人脸人员id:" + value.getPersonId() + ";" + s);
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    String faceid = (String) jsonObject.getJSONObject("data").get("faceId");
                    // 新增数据时,要将海康生成的faceid存入数据库,后面的更新删除要用到
                    if ("success".equals(jsonObject.getString("msg"))) {
                        value.setFaceId(faceid);
                        value.setOperation(0);
                        updatefacelist.add(value);
                    } else {
                        logger.error("新增人脸数据失败,请查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,人脸新增失败");
                }
            }
            if (updatefacelist.size() > 0) {
                faceMP.replaceFaceid(updatefacelist);
            }
            logger.error("成功.....新增符合规范的人脸信息");
        } else {
            logger.error("无可新增的人脸数据");
        }
    }

    // 调用人脸的更新
    // 更新涉及修改和删除
    public void faceUpdate() {
        List<Face> facesUpdate = faceMP.queryUpdate(1);
        List<Face> facesDelete = faceMP.queryDelete(1);
        // 获取全部的更新数据,要进行更新还是删除的判断
        if (facesUpdate.size() > 0) {
            for (Face face : facesUpdate) {
                JSONObject jo = new JSONObject();
                jo.put("faceId", face.getFaceId());
                jo.put("faceData", ImageUtil.getImgUrlToBase64(face.getFaceUrl()));
                try {
                    String s = HikConnection.pushHik("/api/resource/v1/face/single/update", jo.toString());
                    logger.error("修改人脸记录,人脸人员id:" + face.getPersonId() + ";" + s);
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    if ("success".equals(jsonObject.get("msg"))) {
                        faceMP.updateOperation(0, face.getPersonId());
                    } else {
                        logger.error("修改人脸数据失败,清查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,人员更新失败");
                }
            }
            logger.error("成功.....修改符合规范的人脸信息");
        } else {
            logger.error("无需要更新的人员数据");
        }
        // 单个删除
        if (facesDelete.size() > 0) {
            for (Face face : facesDelete) {
                JSONObject jo = new JSONObject();
                String faceId = face.getFaceId();
                jo.put("faceId", faceId);
                try {
                    String s =
                            HikConnection.pushHik("/api/resource/v1/face/single/delete", jo.toJSONString());
                    logger.error("删除人脸记录,人脸人员id:" + face.getPersonId() + ";" + s);
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    if ("success".equals(jsonObject.get("msg"))) {
                        faceMP.updateOperation(0, face.getPersonId());
                    } else {
                        logger.error("删除人脸数据失败,清查看海康返回数据");
                    }
                } catch (Exception e) {
                    logger.error("连接海康服务器失败,未能批量删除人脸数据");
                }
            }
            logger.error("成功.....删除符合规范的人脸信息");
        } else {
            logger.error("无需要删除的人脸数据");
        }
    }
}
